﻿using AutoRegistDependency.Attributes;
using Microsoft.Data.SqlClient;
using Models.Extension;
using Models.Models.Sugar;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Repositories.Base
{
    [Component]
    public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
    {
        protected readonly ISqlSugarClient sqlSugarClient;
        public BaseRepository(ISqlSugarClient sqlSugarClient)
        {
            this.sqlSugarClient = sqlSugarClient;
        }
        public virtual int Add(T entity)
        {
            return sqlSugarClient.Insertable(entity).ExecuteCommand();
        }

        public virtual int Add(List<T> entities)
        {
            return sqlSugarClient.Insertable(entities).ExecuteCommand();
        }

        public virtual Task<int> AddAsync(T entity)
        {
            SqlSugarTransactionAdo? tran= sqlSugarClient.Ado.UseTran();
            return sqlSugarClient.Insertable(entity).ExecuteCommandAsync();
        }

        public virtual Task<int> AddAsync(List<T> entities)
        {
            return sqlSugarClient.Insertable(entities).ExecuteCommandAsync();
        }

        public virtual int Delete(T entity)
        {
            return sqlSugarClient.Deleteable(entity).ExecuteCommand();
        }

        public virtual int Delete(Expression<Func<T, bool>> deleteExpression)
        {
            return sqlSugarClient.Deleteable<T>().Where(deleteExpression).ExecuteCommand();
        }

        public int Delete(List<T> entities)
        {
            return sqlSugarClient.Deleteable(entities).ExecuteCommand();
        }

        public  virtual Task<int> DeleteAsync(T entity)
        {
            return sqlSugarClient.Deleteable(entity).ExecuteCommandAsync();
        }

        public virtual Task<int> DeleteAsync(Expression<Func<T, bool>> deleteExpression)
        {
            return sqlSugarClient.Deleteable<T>().Where(deleteExpression).ExecuteCommandAsync();
        }

        public Task<int> DeleteAsync(List<T> entities)
        {
            return sqlSugarClient.Deleteable(entities).ExecuteCommandAsync();
        }

        public virtual T Find(Expression<Func<T, bool>> findExpression)
        {
            return sqlSugarClient.Queryable<T>().First(findExpression);
        }

        public virtual Task<T> FindAsync(Expression<Func<T, bool>> findExpression)
        {
            return sqlSugarClient.Queryable<T>().FirstAsync(findExpression);
        }

        public virtual int GetCount(Expression<Func<T, bool>> whereExpression)
        {
            return sqlSugarClient.Queryable<T>().Count(whereExpression);
        }

        public virtual Task<int> GetCountAsync(Expression<Func<T, bool>> whereExpression)
        {
            return sqlSugarClient.Queryable<T>().CountAsync(whereExpression);
        }

        public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).ToList();
        }

        public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>> orderExpression, OrderByType orderByType = OrderByType.Asc)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).OrderBy(orderExpression,orderByType).ToList();
        }

        public virtual Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).ToListAsync();
        }

        public virtual Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>> orderExpression, OrderByType orderByType = OrderByType.Asc)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).OrderBy(orderExpression, orderByType).ToListAsync();
        }

        public virtual PageModel<T> GetPaged(Expression<Func<T, bool>> whereExpression, int page, int limit)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).ToPageModel(page,limit);
        }

        public PageModel<T> GetPaged(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>> orderExpression, OrderByType orderByType, int page, int limit)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).OrderBy(orderExpression,orderByType).ToPageModel(page, limit);
        }

        public virtual Task<PageModel<T>> GetPagedAsync(Expression<Func<T, bool>> whereExpression, int page, int limit)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).ToPageModelAsync(page, limit);
        }

        public virtual Task<PageModel<T>> GetPagedAsync(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>> orderExpression, OrderByType orderByType, int page, int limit)
        {
            return sqlSugarClient.Queryable<T>().Where(whereExpression).OrderBy(orderExpression,orderByType).ToPageModelAsync(page, limit);
        }

        public virtual int Update(T entity)
        {
            return sqlSugarClient.Updateable(entity).ExecuteCommand();
        }

        public virtual int Update(List<T> entities)
        {
            return sqlSugarClient.Updateable(entities).ExecuteCommand();
        }

        public virtual Task<int> UpdateAsync(T entity)
        {
            return sqlSugarClient.Updateable(entity).ExecuteCommandAsync();
        }

        public virtual Task<int> UpdateAsync(List<T> entities)
        {
            return sqlSugarClient.Updateable(entities).ExecuteCommandAsync();
        }

        public virtual int UpdateExpression(Expression<Func<T, bool>> whereExpression, Expression<Func<T, T>> setColumns)
        {
            return sqlSugarClient.Updateable<T>().SetColumns(setColumns).Where(whereExpression).ExecuteCommand();
        }

        public virtual int UpdateExpression(Expression<Func<T, bool>> whereExpression, params Expression<Func<T, bool>>[] setColumn)
        {
            var update = sqlSugarClient.Updateable<T>().Where(whereExpression);
            foreach(var set in setColumn)
            {
                update= update.SetColumns(set);
            }
            return update.ExecuteCommand();
        }

        public virtual Task<int> UpdateExpressionAsync(Expression<Func<T, bool>> whereExpression, Expression<Func<T, T>> setColumns)
        {
            return sqlSugarClient.Updateable<T>().SetColumns(setColumns).Where(whereExpression).ExecuteCommandAsync();
        }

        public virtual Task<int> UpdateExpressionAsync(Expression<Func<T, bool>> whereExpression, params Expression<Func<T, bool>>[] setColumn)
        {
            var update = sqlSugarClient.Updateable<T>().Where(whereExpression);
            foreach (var set in setColumn)
            {
                update = update.SetColumns(set);
            }
            return update.ExecuteCommandAsync();
        }
    }
}
